/*
 * Stray Photons - Copyright (C) 2023 Jacob Wirth & Justin Li
 *
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <robin_hood.h>
#include <string>

namespace sp {
    // Keycodes matching GLFW keys
    enum KeyCode : int {
        KEY_INVALID = 0,
        KEY_SPACE = 32,
        KEY_APOSTROPHE = 39,
        KEY_COMMA = 44,
        KEY_MINUS = 45,
        KEY_PERIOD = 46,
        KEY_SLASH = 47,
        KEY_0 = 48,
        KEY_1 = 49,
        KEY_2 = 50,
        KEY_3 = 51,
        KEY_4 = 52,
        KEY_5 = 53,
        KEY_6 = 54,
        KEY_7 = 55,
        KEY_8 = 56,
        KEY_9 = 57,
        KEY_SEMICOLON = 59,
        KEY_EQUALS = 61,
        KEY_A = 65,
        KEY_B = 66,
        KEY_C = 67,
        KEY_D = 68,
        KEY_E = 69,
        KEY_F = 70,
        KEY_G = 71,
        KEY_H = 72,
        KEY_I = 73,
        KEY_J = 74,
        KEY_K = 75,
        KEY_L = 76,
        KEY_M = 77,
        KEY_N = 78,
        KEY_O = 79,
        KEY_P = 80,
        KEY_Q = 81,
        KEY_R = 82,
        KEY_S = 83,
        KEY_T = 84,
        KEY_U = 85,
        KEY_V = 86,
        KEY_W = 87,
        KEY_X = 88,
        KEY_Y = 89,
        KEY_Z = 90,
        KEY_LEFT_BRACKET = 91,
        KEY_BACKSLASH = 92,
        KEY_RIGHT_BRACKET = 93,
        KEY_BACKTICK = 96,
        KEY_ESCAPE = 256,
        KEY_ENTER = 257,
        KEY_TAB = 258,
        KEY_BACKSPACE = 259,
        KEY_INSERT = 260,
        KEY_DELETE = 261,
        KEY_RIGHT_ARROW = 262,
        KEY_LEFT_ARROW = 263,
        KEY_DOWN_ARROW = 264,
        KEY_UP_ARROW = 265,
        KEY_PAGE_UP = 266,
        KEY_PAGE_DOWN = 267,
        KEY_HOME = 268,
        KEY_END = 269,
        KEY_CAPS_LOCK = 280,
        KEY_SCROLL_LOCK = 281,
        KEY_NUM_LOCK = 282,
        KEY_PRINT_SCREEN = 283,
        KEY_PAUSE = 284,
        KEY_F1 = 290,
        KEY_F2 = 291,
        KEY_F3 = 292,
        KEY_F4 = 293,
        KEY_F5 = 294,
        KEY_F6 = 295,
        KEY_F7 = 296,
        KEY_F8 = 297,
        KEY_F9 = 298,
        KEY_F10 = 299,
        KEY_F11 = 300,
        KEY_F12 = 301,
        KEY_F13 = 302,
        KEY_F14 = 303,
        KEY_F15 = 304,
        KEY_F16 = 305,
        KEY_F17 = 306,
        KEY_F18 = 307,
        KEY_F19 = 308,
        KEY_F20 = 309,
        KEY_F21 = 310,
        KEY_F22 = 311,
        KEY_F23 = 312,
        KEY_F24 = 313,
        KEY_F25 = 314,
        KEY_0_NUMPAD = 320,
        KEY_1_NUMPAD = 321,
        KEY_2_NUMPAD = 322,
        KEY_3_NUMPAD = 323,
        KEY_4_NUMPAD = 324,
        KEY_5_NUMPAD = 325,
        KEY_6_NUMPAD = 326,
        KEY_7_NUMPAD = 327,
        KEY_8_NUMPAD = 328,
        KEY_9_NUMPAD = 329,
        KEY_DECIMAL_NUMPAD = 330,
        KEY_DIVIDE_NUMPAD = 331,
        KEY_MULTIPLY_NUMPAD = 332,
        KEY_MINUS_NUMPAD = 333,
        KEY_PLUS_NUMPAD = 334,
        KEY_ENTER_NUMPAD = 335,
        KEY_EQUALS_NUMPAD = 336,
        KEY_LEFT_SHIFT = 340,
        KEY_LEFT_CONTROL = 341,
        KEY_LEFT_ALT = 342,
        KEY_LEFT_SUPER = 343,
        KEY_RIGHT_SHIFT = 344,
        KEY_RIGHT_CONTROL = 345,
        KEY_RIGHT_ALT = 346,
        KEY_RIGHT_SUPER = 347,
        KEY_CONTEXT_MENU = 348,
    };

    enum InputAction : int {
        RELEASE = 0,
        PRESS = 1,
        REPEAT = 2,
    };

    enum MouseButton : int {
        BUTTON_LEFT = 0,
        BUTTON_RIGHT = 1,
        BUTTON_MIDDLE = 2,
        BUTTON_4 = 3,
        BUTTON_5 = 4,
        BUTTON_6 = 5,
        BUTTON_7 = 6,
        BUTTON_8 = 7,
    };

    static const robin_hood::unordered_flat_map<KeyCode, std::string> KeycodeNameLookup = {
        {KEY_SPACE, "space"},
        {KEY_APOSTROPHE, "apostrophe"},
        {KEY_COMMA, "comma"},
        {KEY_MINUS, "minus"},
        {KEY_PERIOD, "period"},
        {KEY_SLASH, "slash"},
        {KEY_0, "0"},
        {KEY_1, "1"},
        {KEY_2, "2"},
        {KEY_3, "3"},
        {KEY_4, "4"},
        {KEY_5, "5"},
        {KEY_6, "6"},
        {KEY_7, "7"},
        {KEY_8, "8"},
        {KEY_9, "9"},
        {KEY_SEMICOLON, "semicolon"},
        {KEY_EQUALS, "equals"},
        {KEY_A, "a"},
        {KEY_B, "b"},
        {KEY_C, "c"},
        {KEY_D, "d"},
        {KEY_E, "e"},
        {KEY_F, "f"},
        {KEY_G, "g"},
        {KEY_H, "h"},
        {KEY_I, "i"},
        {KEY_J, "j"},
        {KEY_K, "k"},
        {KEY_L, "l"},
        {KEY_M, "m"},
        {KEY_N, "n"},
        {KEY_O, "o"},
        {KEY_P, "p"},
        {KEY_Q, "q"},
        {KEY_R, "r"},
        {KEY_S, "s"},
        {KEY_T, "t"},
        {KEY_U, "u"},
        {KEY_V, "v"},
        {KEY_W, "w"},
        {KEY_X, "x"},
        {KEY_Y, "y"},
        {KEY_Z, "z"},
        {KEY_LEFT_BRACKET, "left_bracket"},
        {KEY_BACKSLASH, "backslash"},
        {KEY_RIGHT_BRACKET, "right_bracket"},
        {KEY_BACKTICK, "backtick"},
        {KEY_ESCAPE, "escape"},
        {KEY_ENTER, "enter"},
        {KEY_TAB, "tab"},
        {KEY_BACKSPACE, "backspace"},
        {KEY_INSERT, "insert"},
        {KEY_DELETE, "delete"},
        {KEY_RIGHT_ARROW, "right_arrow"},
        {KEY_LEFT_ARROW, "left_arrow"},
        {KEY_DOWN_ARROW, "down_arrow"},
        {KEY_UP_ARROW, "up_arrow"},
        {KEY_PAGE_UP, "page_up"},
        {KEY_PAGE_DOWN, "page_down"},
        {KEY_HOME, "home"},
        {KEY_END, "end"},
        {KEY_CAPS_LOCK, "caps_lock"},
        {KEY_SCROLL_LOCK, "scroll_lock"},
        {KEY_NUM_LOCK, "num_lock"},
        {KEY_PRINT_SCREEN, "print_screen"},
        {KEY_PAUSE, "pause"},
        {KEY_F1, "f1"},
        {KEY_F2, "f2"},
        {KEY_F3, "f3"},
        {KEY_F4, "f4"},
        {KEY_F5, "f5"},
        {KEY_F6, "f6"},
        {KEY_F7, "f7"},
        {KEY_F8, "f8"},
        {KEY_F9, "f9"},
        {KEY_F10, "f10"},
        {KEY_F11, "f11"},
        {KEY_F12, "f12"},
        {KEY_F13, "f13"},
        {KEY_F14, "f14"},
        {KEY_F15, "f15"},
        {KEY_F16, "f16"},
        {KEY_F17, "f17"},
        {KEY_F18, "f18"},
        {KEY_F19, "f19"},
        {KEY_F20, "f20"},
        {KEY_F21, "f21"},
        {KEY_F22, "f22"},
        {KEY_F23, "f23"},
        {KEY_F24, "f24"},
        {KEY_F25, "f25"},
        {KEY_0_NUMPAD, "0_numpad"},
        {KEY_1_NUMPAD, "1_numpad"},
        {KEY_2_NUMPAD, "2_numpad"},
        {KEY_3_NUMPAD, "3_numpad"},
        {KEY_4_NUMPAD, "4_numpad"},
        {KEY_5_NUMPAD, "5_numpad"},
        {KEY_6_NUMPAD, "6_numpad"},
        {KEY_7_NUMPAD, "7_numpad"},
        {KEY_8_NUMPAD, "8_numpad"},
        {KEY_9_NUMPAD, "9_numpad"},
        {KEY_DECIMAL_NUMPAD, "decimal_numpad"},
        {KEY_DIVIDE_NUMPAD, "divide_numpad"},
        {KEY_MULTIPLY_NUMPAD, "multiply_numpad"},
        {KEY_MINUS_NUMPAD, "minus_numpad"},
        {KEY_PLUS_NUMPAD, "plus_numpad"},
        {KEY_ENTER_NUMPAD, "enter_numpad"},
        {KEY_EQUALS_NUMPAD, "equals_numpad"},
        {KEY_LEFT_SHIFT, "left_shift"},
        {KEY_LEFT_CONTROL, "left_control"},
        {KEY_LEFT_ALT, "left_alt"},
        {KEY_LEFT_SUPER, "left_super"},
        {KEY_RIGHT_SHIFT, "right_shift"},
        {KEY_RIGHT_CONTROL, "right_control"},
        {KEY_RIGHT_ALT, "right_alt"},
        {KEY_RIGHT_SUPER, "right_super"},
        {KEY_CONTEXT_MENU, "context_menu"},
    };

    static const robin_hood::unordered_flat_map<std::string, KeyCode> NameKeycodeLookup = [] {
        robin_hood::unordered_flat_map<std::string, KeyCode> map;
        for (auto &[keyCode, name] : KeycodeNameLookup) {
            map[name] = keyCode;
        }
        return map;
    }();

    // All inputs in lowercase to allow for case-insensitivity
    static const robin_hood::unordered_flat_map<std::string, std::string> UserBindingAliases = {
        {" ", "space"},
        {"'", "apostrophe"},
        {",", "comma"},
        {"-", "minus"},
        {".", "period"},
        {"/", "slash"},
        {";", "semicolon"},
        {"=", "equals"},
        {"[", "left_bracket"},
        {"\\", "backslash"},
        {"]", "right_bracket"},
        {"grave_accent", "backtick"},
        {"`", "backtick"},

        {"esc", "escape"},
        {"del", "delete"},
        {"right", "arrow_right"},
        {"left", "arrow_left"},
        {"down", "arrow_down"},
        {"up", "arrow_up"},
        {"capslock", "caps_lock"},
        {"scrolllock", "scroll_lock"},
        {"numlock", "num_lock"},
        {"printscreen", "print_screen"},

        {"numpad_0", "0_numpad"},
        {"num_0", "0_numpad"},
        {"numpad_1", "1_numpad"},
        {"num_1", "1_numpad"},
        {"numpad_2", "2_numpad"},
        {"num_2", "2_numpad"},
        {"numpad_3", "3_numpad"},
        {"num_3", "3_numpad"},
        {"numpad_4", "4_numpad"},
        {"num_4", "4_numpad"},
        {"numpad_5", "5_numpad"},
        {"num_5", "5_numpad"},
        {"numpad_6", "6_numpad"},
        {"num_6", "6_numpad"},
        {"numpad_7", "7_numpad"},
        {"num_7", "7_numpad"},
        {"numpad_8", "8_numpad"},
        {"num_8", "8_numpad"},
        {"numpad_9", "9_numpad"},
        {"num_9", "9_numpad"},

        {"period_numpad", "decimal_numpad"},
        {"numpad_period", "decimal_numpad"},
        {"num_period", "decimal_numpad"},
        {"numpad_decimal", "decimal_numpad"},
        {"num_decimal", "decimal_numpad"},

        {"numpad_divide", "divide_numpad"},
        {"num_divide", "divide_numpad"},

        {"numpad_multiply", "multiply_numpad"},
        {"num_multiply", "multiply_numpad"},

        {"numpad_minus", "minus_numpad"},
        {"num_minus", "minus_numpad"},
        {"numpad_subtract", "minus_numpad"},
        {"num_subtract", "minus_numpad"},

        {"numpad_plus", "plus_numpad"},
        {"num_plus", "plus_numpad"},
        {"numpad_add", "plus_numpad"},
        {"num_add", "plus_numpad"},

        {"numpad_enter", "enter_numpad"},
        {"num_enter", "enter_numpad"},

        {"numpad_equals", "equals_numpad"},
        {"num_equals", "equals_numpad"},

        {"shift_left", "left_shift"},
        {"control_left", "left_control"},
        {"alt_left", "left_alt"},
        {"super_left", "left_super"},
        {"shift_right", "right_shift"},
        {"control_right", "right_control"},
        {"alt_right", "right_alt"},
        {"super_right", "right_super"},

        {"menu", "context_menu"},
    };
} // namespace sp
